#include "./Game/Obj/GameObj.h"
#include "./Game/GAME.h"
#include <iostream>
using namespace std ;
using namespace Game::Obj;
using namespace Game ;

int main(){
//    Player player;
//    Bullet bullet ;
    GAME game ;
    sf::RenderWindow window(sf::VideoMode(1280, 720), "Player with Orbiting Bullet");
    BackgroundRenderer backgroundRenderer("../resource/img/background.png");
    game._show_collider = true ;

    sf::Clock clock;
    while (window.isOpen() and not game._over) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }

        float deltaTime = clock.restart().asSeconds();
        game.update(deltaTime);
        window.clear();
        window.draw(backgroundRenderer);
        game.draw(window);
        window.display();
    }

    return 0;

}




#ifdef PLAYER

#include <iostream>

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <string>
#include <utility>
#include <vector>
#include "./utils/Vector.h"
using namespace std ;
#include "./Graphic/Graphic.h"
using namespace Game::Graphic;

#include <SFML/Graphics.hpp>
#include <vector>
#include <cmath>

class Bullet {
public:
    Vector2f position;
    sf::CircleShape circle;

    Bullet() {
        circle = sf::CircleShape(10);
        circle.setFillColor(sf::Color::Red);
    }

    void setPosition(Vector2f p) {
        this->position = p;
        circle.setPosition(p.x, p.y);
    }

    Vector2f getPosition() const {
        return position;
    }

    void draw(sf::RenderWindow& window) {
        window.draw(circle);
    }
};

class Player {
public:
    Animation animaR;
    Vector2f position;
    Bullet bullet;
    float bulletAngle;
    float bulletOrbitRadius;

    Player()
            : bulletAngle(0.0f), bulletOrbitRadius(80.0f) {
        animaR = AnimationBuilder()
                .addPath("../resource/img/player_left_0.png")
                .addPath("../resource/img/player_left_1.png")
                .addPath("../resource/img/player_left_2.png")
                .addPath("../resource/img/player_left_3.png")
                .addPath("../resource/img/player_left_4.png")
                .addPath("../resource/img/player_left_5.png")
                .position({300, 400})
                .interval(1)
                .opacity(0.8f)
                .loop(true)
                .pause()
                .play()
                .scale({150,150})
                .build();
        position = animaR.getPosition();
    }

    void update(float deltaTime) {
        animaR.update(deltaTime);
//        position = animaR.getPosition();
//
//        // 获取玩家动画的尺寸
//        sf::Vector2f playerSize(animaR.getScale().x, animaR.getScale().y);
//
//        // 计算玩家图像的中心点
//        sf::Vector2f playerCenter(position.x + playerSize.x / 2, position.y + playerSize.y / 2);
//
//        // 更新子弹角度
//        bulletAngle += deltaTime; // 控制子弹的旋转速度
//
//        // 计算子弹位置
//        float bulletX = playerCenter.x + bulletOrbitRadius * cos(bulletAngle) - bullet.circle.getRadius();
//        float bulletY = playerCenter.y + bulletOrbitRadius * sin(bulletAngle) - bullet.circle.getRadius();
//
//        // 更新子弹位置
//        bullet.setPosition(Vector2f(bulletX, bulletY));
        auto p1 = animaR.getPosition();
        auto p2 = p1 + Vector2f ({
                                         animaR.getScale().x / 2,
                                         animaR.getScale().y / 2
                                 });

        bulletAngle += deltaTime * 50; // 控制子弹的旋转速度
        auto p3 = p2 +
                  bulletOrbitRadius *
                  Vector2f ({
                                    cos(bulletAngle),
                                    sin(bulletAngle)
                            });
//        cout << bullet.circle.getScale().x << endl ;
        auto p4 = p3 - Vector2f ({
                                         bullet.circle.getRadius(),
                                         bullet.circle.getRadius()
                                 });
//        bullet.circle.
        bullet.setPosition(p4);
    }

    void draw(sf::RenderWindow& window) {
        window.draw(animaR);
        bullet.draw(window);
    }
};

int main() {
    sf::RenderWindow window(sf::VideoMode(1280, 720), "Player with Orbiting Bullet");
    BackgroundRenderer backgroundRenderer("../resource/img/background.png");

    Player player;

    sf::Clock clock;
    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }

        float deltaTime = clock.restart().asSeconds();
        player.update(deltaTime);

        window.clear();
        window.draw(backgroundRenderer);

        player.draw(window);
        window.display();
    }

    return 0;
}



#ifdef COLLISION

#include "./Physics/Collision/Collision.h"
#include "./Physics/Collision/visual.h"

class Controller {
public:
    void control(Game::Phy::Collision::AABB& box, float deltaTime) {
        float speed = 200.0f; // speed in pixels per second
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
            box.position.x -= speed * deltaTime;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
            box.position.x += speed * deltaTime;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
            box.position.y -= speed * deltaTime;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
            box.position.y += speed * deltaTime;
        }
    }
};

int main() {
    using namespace Game::Phy::Collision;
    using namespace sf;

    RenderWindow window(VideoMode(800, 600), "Collision Detection");

    AABB box1(Vector2f(100, 100), Vector2f(100, 100));
//    AABB box2(Vector2f(300, 300), Vector2f(100, 100));

    CircleCollider circle1(Vector2f(300, 200), 50);
//    CircleCollider circle2(Vector2f(200, 200), 100);

//    PointCollider point1(Vector2f(200, 400));
//    PointCollider point2(Vector2f(150, 300));

    Controller controller;
    Clock clock;

    std::map<std::string, bool> collisionMap; // To track collision states with each object
    bool lastCollisionState = false; // To track the previous collision state

    int cnt = 0 ;

    while (window.isOpen()) {
        Event event;
        while (window.pollEvent(event)) {
            if (event.type == Event::Closed)
                window.close();
        }

        float deltaTime = clock.restart().asSeconds();
        controller.control(box1, deltaTime);

//        bool box1ToBox2 = box1.intersect(box2);
        bool box1ToCircle1 = box1.intersect(circle1);
//        bool box1ToCircle2 = box1.intersect(circle2);
//        bool box1ToPoint1 = box1.intersect(point1);
//        bool box1ToPoint2 = box1.intersect(point2);

        // Update collision map
//        collisionMap["Box2"] = box1ToBox2;
        collisionMap["Circle1"] = box1ToCircle1;
//        collisionMap["Circle2"] = box1ToCircle2;
//        collisionMap["Point1"] = box1ToPoint1;
//        collisionMap["Point2"] = box1ToPoint2;

        // Check if any collision occurred
        bool currentCollisionState =  box1ToCircle1 ;//|| box1ToCircle2 || box1ToPoint1 || box1ToPoint2;

        // Output collision result only when it changes
        if (currentCollisionState && !lastCollisionState) {
            cnt ++ ;
            std::cout << "Box1 intersects with:";
            for (const auto& pair : collisionMap) {
                if (pair.second) {
                    std::cout << " " << pair.first;
                }
                std::cout << "for " << cnt << " times";
            }
            std::cout << std::endl;
        }

        lastCollisionState = currentCollisionState;

        window.clear();
        drawCollider(window, box1);
//        drawCollider(window, box2);
        drawCollider(window, circle1);
//        drawCollider(window, circle2);
//        drawCollider(window, point1);
//        drawCollider(window, point2);

        window.display();
    }

    return 0;
}
#endif



#ifdef CIRCLE

int main() {
    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Circle");

    // 创建一个圆形
    sf::CircleShape circle(50);
    circle.setFillColor(sf::Color::Green);
    circle.setPosition(375, 275);

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        window.draw(circle); // 绘制圆形
        window.display();
    }

    return 0;
}

#endif

#ifdef EASYX

#include<graphics.h>
#include<string>
#include<vector>
#include<math.h>

//�����±�
int idx_current_anim = 0;

const int WINDOW_WIDTH = 1280;
const int WINDOW_HEIGHT = 720;

//��������
const int PLAYER_ANIM_NUM = 6;

//�������ﶯ��ͼƬ
IMAGE img_player_left[PLAYER_ANIM_NUM];
IMAGE img_player_right[PLAYER_ANIM_NUM];

//��ʼ���λ��
POINT player_position = { 500,500 };


#pragma comment(lib,"MSIMG32.LIB")
//���Ʋ���ʾͼ�񣨻��͸����
inline void putimage_alpha(int x, int y, IMAGE* img)
{
    int w = img->getwidth();
    int h = img->getheight();
    AlphaBlend(GetImageHDC(NULL), x, y, w, h,
               GetImageHDC(img), 0, 0, w, h, { AC_SRC_OVER,0,255,AC_SRC_ALPHA });
}

////������Ҷ���-��ʼ��
//void LoadAnimation()
//{
//	for (size_t i = 0; i < PLAYER_ANIM_NUM; i++)
//	{
//		std::wstring path = L"img/player_left_" + std::to_wstring(i) + L".png";
//		loadimage(&img_player_left[i], path.c_str());
//	}
//	for (size_t i = 0; i < PLAYER_ANIM_NUM; i++)
//	{
//		std::wstring path = L"img/player_right_" + std::to_wstring(i) + L".png";
//		loadimage(&img_player_right[i], path.c_str());
//	}
//}

//��������-��
class Animation
{
public:
    Animation(LPCTSTR path, int num, int interval)
    {
        interval_ms = interval;

        TCHAR path_file[256];
        for (int i = 0; i < num; i++)
        {
            _stprintf_s(path_file, path, i);

            IMAGE* frame = new IMAGE();
            loadimage(frame, path_file);
            frame_list.push_back(frame);
        }
    }

    void play(int x, int y, int delta)
    {
        timer += delta;
        if (timer >= interval_ms)
        {
            idx_frame = (idx_frame + 1) % frame_list.scale();
            timer = 0;
        }

        putimage_alpha(x, y, frame_list[idx_frame]);
    }

    ~Animation()
    {
        for (size_t i = 0; i < frame_list.scale(); i++)
        {
            delete frame_list[i];
        }
    }
private:
    int timer = 0;			//������ʱ��
    int idx_frame = 0;		//����֡����
    int interval_ms = 0;
    std::vector<IMAGE*> frame_list;
};

class Player
{
public:
    Player()
    {
        loadimage(&img_shadow, _T("img/shadow_player.png"));
        anim_right = new Animation(_T("img/1��4��(%d).png"), 13, 180);
        anim_left = new Animation(_T("img/1��4��(%d).png"), 13,180);
    }

    ~Player()
    {
        delete anim_left;
        delete anim_right;
    }

    void ProcessEvent(const ExMessage& msg)
    {
        switch (msg.message)
        {
            case WM_KEYDOWN:
                switch (msg.vkcode)
                {
                    case VK_UP:
                        is_move_up = true;
                        break;
                    case VK_DOWN:
                        is_move_down = true;
                        break;
                    case VK_LEFT:
                        is_move_left = true;
                        break;
                    case VK_RIGHT:
                        is_move_right = true;
                        break;
                }
                break;

                //����״̬�ж�
            case WM_KEYUP:
                switch (msg.vkcode)
                {
                    case VK_UP:
                        is_move_up = false;
                        break;
                    case VK_DOWN:
                        is_move_down = false;
                        break;
                    case VK_LEFT:
                        is_move_left = false;
                        break;
                    case VK_RIGHT:
                        is_move_right = false;
                        break;
                }
                break;
        }
    }

    void Move()
    {
        int dir_x = is_move_right - is_move_left;
        int dir_y = is_move_down - is_move_up;
        //�����ƶ��ĵ�λ����
        double len_dir = sqrt(dir_x * dir_x + dir_y * dir_y);
        //����λ���Ե�λ�ٶ��ƶ�
        if (len_dir != 0)
        {
            double normalized_x = dir_x / len_dir;
            double normalized_y = dir_y / len_dir;
            position.x += (int)(SPEED * normalized_x);
            position.y += (int)(SPEED * normalized_y);
        }

        //���������ڴ������ƶ�
        if (position.x < 0) position.x = 0;
        if (position.y < 0) position.y = 0;
        if (position.x + PLAYER_WIDTH > WINDOW_WIDTH) position.x = WINDOW_WIDTH - PLAYER_WIDTH;
        if (position.y + PLAYER_HEIGHT > WINDOW_WIDTH) position.y = WINDOW_HEIGHT - PLAYER_HEIGHT;

    }

    void Draw(int delta)
    {
        int pos_shadow_x = position.x + (PLAYER_WIDTH / 2 - SHADOW_WIDTH / 2);
        int pos_shadow_y = position.y + PLAYER_HEIGHT - 8;
        putimage_alpha(pos_shadow_x, pos_shadow_y, &img_shadow);

        static bool facing_left = false;
        int dir_x = is_move_right - is_move_left;
        if (dir_x < 0)
            facing_left = true;
        else if (dir_x > 0)
            facing_left = false;

        if (facing_left)
        {
            anim_left->play(position.x, position.y, delta);
        }
        else
        {
            anim_right->play(position.x, position.y, delta);
        }
    }

    const POINT& GetPosition() const
    {
        return position;
    }

private:
    const int SPEED = 5;			//����ƶ��ٶ�
    const int PLAYER_WIDTH = 80;	//��ҿ��
    const int PLAYER_HEIGHT = 80;	//��Ҹ߶�
    const int SHADOW_WIDTH = 32;	//��Ӱ���

    IMAGE img_shadow;
    Animation* anim_left;
    Animation* anim_right;
    POINT position = { 600,300 };
    //�����жϰ���״̬�ı���
    bool is_move_up = false;
    bool is_move_down = false;
    bool is_move_left = false;
    bool is_move_right = false;
};

class Bullet
{
public:
    POINT position = { 0,0 };
public:
    Bullet() = default;
    ~Bullet() = default;

    void Draw() const
    {
        setlinecolor(RGB(255, 155, 50));
        setlinecolor(RGB(200, 75, 10));
        fillcircle(position.x, position.y, RADIUS);
    }

private:
    const int RADIUS = 10;
};

class Enemy
{
public:
    Enemy()
    {
        loadimage(&img_shadow, _T("img/shadow_enemy.png"));
        anim_right = new Animation(_T("img/enemy_right_%d.png"), 6, 45);
        anim_left = new Animation(_T("img/enemy_left_%d.png"), 6, 45);

        //�������ɱ߽�
        enum class SpawnEdge
        {
            Up = 0,
            Down,
            Left,
            Right
        };
        //�����˷����ڵ�ͼ��߽紦��������λ��
        SpawnEdge edge = (SpawnEdge)(rand() % 4);
        switch (edge)
        {
            case SpawnEdge::Up:
                position.x = rand() % WINDOW_WIDTH;
                position.y = -ENEMY_HEIGHT;
                break;
            case SpawnEdge::Down:
                position.x = rand() % WINDOW_WIDTH;
                position.y = WINDOW_HEIGHT;
                break;
            case SpawnEdge::Left:
                position.x = -ENEMY_HEIGHT;
                position.y = rand() % WINDOW_HEIGHT;
                break;
            case SpawnEdge::Right:
                position.x = WINDOW_WIDTH;
                position.y = rand() % WINDOW_HEIGHT;
                break;
            default:
                break;

        }
    }

    bool CheckBulletCollision(const Bullet& bullet)
    {
        //���ӵ���ЧΪ�㣬�жϵ��Ƿ��ڵ��˾�����
        return false;

    }

    bool CheckPlayerCollision(const Player& Player)
    {
        return false;
    }

    void Move(const Player& player)
    {
        const POINT& player_position = player.GetPosition();
        int dir_x = player_position.x - position.x;
        int dir_y = player_position.y - position.y;
        double len_dir = sqrt(dir_x * dir_x + dir_y * dir_y);
        if (len_dir != 0)
        {
            double normalized_x = dir_x / len_dir;
            double normalized_y = dir_y / len_dir;
            position.x += (int)(SPEED * normalized_x);
            position.y += (int)(SPEED * normalized_y);
        }

        if (dir_x < 0)
            facing_left = true;
        else if (dir_x > 0)
            facing_left = false;

    }

    void Draw(int delta)
    {
        int pos_shadow_x = position.x + (ENEMY_WIDTH / 2 - SHADOW_WIDTH / 2);
        int pos_shadow_y = position.y + ENEMY_HEIGHT - 32;
        putimage_alpha(pos_shadow_x, pos_shadow_y, &img_shadow);

        if (facing_left)
            anim_left->play(position.x, position.y, delta);
        else
            anim_right->play(position.x, position.y, delta);
    }

    ~Enemy()
    {
        delete anim_left;
        delete anim_right;
    }
private:
    const int SPEED = 2;			//�����ƶ��ٶ�
    const int ENEMY_WIDTH = 80;		//���˿��
    const int ENEMY_HEIGHT = 80;	//���˸߶�
    const int SHADOW_WIDTH = 48;	//��Ӱ���

private:
    IMAGE img_shadow;
    Animation* anim_left;
    Animation* anim_right;
    POINT position = { 0,0 };
    bool facing_left = false;
};

//�����µĵ���
void TryGenerateEnemy(std::vector<Enemy*>& enemy_list)
{
    const int INTERVAL = 100;
    static int counter = 0;
    if ((++counter) % INTERVAL == 0)
        enemy_list.push_back(new Enemy());
}

int main()
{
    //���ƴ���
    initgraph(1280, 720);

    //�жϳ�������
    bool running = true;

    //��ұ���
    Player player;
    //�洢���˶���ָ��
    std::vector<Enemy*> enemy_list;

    //��Ϣ����
    ExMessage msg;

    //����ͼƬ����
    IMAGE img_backgroud;

    //�����жϰ���״̬�ı���
    bool is_move_up = false;
    bool is_move_down = false;
    bool is_move_left = false;
    bool is_move_right = false;


    //���ر���
    loadimage(&img_backgroud, _T("img/background.png"));
    //loadimage(&img_shadow, _T("img/shadow_player.png"));

    BeginBatchDraw();

    while (running)
    {
        DWORD start_time = GetTickCount();

        //������Ϣ������
        while (peekmessage(&msg))
        {
            player.ProcessEvent(msg);
        }

        //����ƶ�
        player.Move();
        //�����µĵ���
        TryGenerateEnemy(enemy_list);
        for (Enemy* enemy : enemy_list)
            enemy->Move(player);

        //�����Ļ
        cleardevice();

        //��ʾ����ͼ
        putimage(0, 0, &img_backgroud);

        //���ƻ���
        player.Draw(1000 / 144);
        for (Enemy* enemy : enemy_list)
            enemy->Draw(1000 / 144);

        FlushBatchDraw();

        //��ʱ֡�ʴ���
        DWORD end_time = GetTickCount();
        DWORD delta_time = end_time - start_time;
        if (delta_time < 1000 / 144)
        {
            Sleep(1000 / 144 - delta_time);
        }
    }

    EndBatchDraw();

    return 0;
}

#endif


#endif